/**
 *                            License
 * THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS  
 * CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). 
 * THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW.  
 * ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR  
 * COPYRIGHT LAW IS PROHIBITED.
 * 
 * BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND  
 * AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE  
 * MAY BE CONSIDERED TO BE A CONTRACT,
 * THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED 
 * HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.
 * 
 */
package lineage.util;

/**
 * 坐标点.
 * 
 * @version 2014年4月5日下午8:24:30
 * @author jrwz
 */
public class L1Point {
    // 正向
    public static final byte[] HEADING_TABLE_X = { 0, 1, 1, 1, 0, -1, -1, -1 };
    public static final byte[] HEADING_TABLE_Y = { -1, -1, 0, 1, 1, 1, 0, -1 };
    // 反向
    public static final byte[] HEADING_TABLE_XR = { 0, -1, -1, -1, 0, 1, 1, 1 };
    public static final byte[] HEADING_TABLE_YR = { 1, 1, 0, -1, -1, -1, 0, 1 };
    protected int x;
    protected int y;

    public L1Point() {
    }

    public L1Point(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    public L1Point(final L1Point pt) {
        this.x = pt.x;
        this.y = pt.y;
    }

    /**
     * 取得x坐标.
     * 
     * @return x坐标
     */
    public int getX() {
        return x;
    }

    /**
     * 设置x坐标.
     * 
     * @param x
     *            - 要设置的x坐标
     */
    public void setX(final int x) {
        this.x = x;
    }

    /**
     * 取得y坐标.
     * 
     * @return y坐标
     */
    public int getY() {
        return y;
    }

    /**
     * 设置y坐标.
     * 
     * @param y
     *            - 要设置的y坐标
     */
    public void setY(final int y) {
        this.y = y;
    }

    /**
     * 设置坐标点.
     * 
     * @param pt
     *            - 要设置的坐标点
     */
    public void set(final L1Point pt) {
        set(pt.x, pt.y);
    }

    /**
     * 设置坐标点.
     * 
     * @param x
     *            - 要设置的x坐标
     * @param y
     *            - 要设置的y坐标
     */
    public void set(final int x, final int y) {
        this.x = x;
        this.y = y;
    }

    /**
     * 指定面向前进位置坐标.
     * 
     * @param heading
     *            - 面向(0~7)
     */
    public void forward(final int heading) {
        x += HEADING_TABLE_X[heading];
        y += HEADING_TABLE_Y[heading];
    }

    /**
     * 指定面向反向前进位置坐标.
     * 
     * @param heading
     *            - 面向(0~7)
     */
    public void backward(final int heading) {
        x -= HEADING_TABLE_X[heading];
        y -= HEADING_TABLE_Y[heading];
    }

    /**
     * 取得指定坐标的直线距离.
     * 
     * @param pt
     *            - L1Point对象
     * @return 距离
     */
    public double getLineDistance(final L1Point pt) {
        return getLineDistance(pt.getX(), pt.getY());
    }

    /**
     * 取得指定坐标的直线距离.
     * 
     * @param x
     *            - x坐标
     * @param y
     *            - y坐标
     * @return 距离
     */
    public double getLineDistance(final int x, final int y) {
        final long diffX = x - getX();
        final long diffY = y - getY();
        return Math.sqrt((diffX * diffX) + (diffY * diffY));
    }

    /**
     * 取得指定坐标直线距离(相对位置最大距离).
     * 
     * @param pt
     *            - L1Point对象
     * @return 距离
     */
    public int getTileLineDistance(final L1Point pt) {
        return Math.max(Math.abs(pt.getX() - getX()), Math.abs(pt.getY() - getY()));
    }

    /**
     * 取得指定坐标距离(XY距离总合).
     * 
     * @param pt
     *            - L1Point对象
     * @return 距离
     */
    public int getTileDistance(final L1Point pt) {
        return Math.abs(pt.getX() - getX()) + Math.abs(pt.getY() - getY());
    }

    /**
     * 是否在指定坐标的19格范围内(屏幕内).
     * 
     * @param pt
     *            - L1Point对象
     * @return 如果是则返回true
     */
    public boolean isInScreen(final L1Point pt) {
        final int dist = getTileDistance(pt);
        if (dist > 19) { // 当tile距离 > 19 的时候，判断为不在画面内(false)
            return false;
        } else if (dist <= 18) { // 当tile距离 <= 18 的时候，判断为位于同一个画面内(true)
            return true;
        } else {
            // 显示区的坐标系统 (18, 18)
            final int dist2 = Math.abs(pt.getX() - (getX() - 18)) + Math.abs(pt.getY() - (getY() - 18));
            if ((dist2 >= 19) && (dist2 <= 52)) {
                return true;
            }
            return false;
        }
    }

    /**
     * 是否与指定的坐标位置重叠.
     * 
     * @param pt
     *            - L1Point对象
     * @return 如果是则返回true
     */
    public boolean isSamePoint(final L1Point pt) {
        return (pt.getX() == getX()) && (pt.getY() == getY());
    }

    @Override
    public boolean equals(final Object obj) {
        if (!(obj instanceof L1Point)) {
            return false;
        }
        final L1Point pt = (L1Point) obj;
        return (getX() == pt.getX()) && (getY() == pt.getY());
    }

    @Override
    public int hashCode() {
        return 7 * getX() + getY();
    }

    @Override
    public String toString() {
        return String.format("(%d, %d)", x, y);
    }
}
